import store from '../base/store'
import Sprite from '../base/sprite'

/**
 * 小鸟精灵
 * @description 准备三个小鸟的状态，渲染时不断刷新这三张状态图来模拟小鸟飞行，实际上就是不断的剪裁小鸟图
 */
export class BirdSprite extends Sprite {
  /** 小鸟切换数据 */
  private birdSpriteData: {
    sx: number
    sy: number
    sw: number
    sh: number
  }[] = []
  /** 小鸟切换计数 */
  private clipCount = 0
  /** 小鸟切换index */
  private clipIndex = 0
  /** 小鸟y轴速度 */
  private vy = 0
  /** 小鸟角度 */
  private angle = 0
  /** 小鸟角速度 */
  private va = 0
  /** 小鸟重力加速度 */
  private readonly g: number = 0.25
  /** 小鸟角加速度 */
  private readonly a: number = 0.005

  constructor() {
    const image = Sprite.getMap('sprites')
    const upBird = Sprite.getSpritesData('upBird')
    const middleBird = Sprite.getSpritesData('middleBird')
    const downBird = Sprite.getSpritesData('downBird')
    const w = upBird.sw * 3
    const h = w * (upBird.sh / upBird.sw)
    super(
      image,
      upBird.sx,
      upBird.sy,
      upBird.sw,
      upBird.sh,
      store.canvas.width / 4,
      store.canvas.height / 2.5,
      w,
      h
    )
    this.birdSpriteData = [upBird, middleBird, downBird]
  }

  /**
   * 小鸟起飞
   * @returns 精灵实例
   */
  public fly(): BirdSprite {
    this.vy = -5
    this.va = -0.1
    return this
  }

  /**
   * 绘制函数：小鸟循环切换 + y轴运动 + 旋转运动
   * @returns 无
   */
  public override draw(): void {
    this.ctx.save()

    // 1.小鸟循环切换
    this.clipCount =
      this.clipIndex >= this.birdSpriteData.length - 1
        ? 0
        : this.clipCount + 0.2
    this.clipIndex = Math.floor(this.clipCount)
    const spriteData = this.birdSpriteData[this.clipIndex]

    // 2.小鸟y轴运动
    this.vy += this.g // 累加重力加速度
    this.y += this.vy // 计算y轴位置

    // 3.小鸟旋转运动
    this.va += this.a // 累加角速度
    this.angle += this.va
    if (this.angle >= Math.PI / 3) {
      this.angle = Math.PI / 3 // 最大角度
    } else if (this.angle <= -Math.PI / 3) {
      this.angle = -Math.PI / 3 // 最小角度
    }
    // canvas旋转是基于绘图区域原点的，因此需要调整到精灵原点
    this.ctx.translate(this.x + this.w / 2, this.y + this.h / 2)
    this.ctx.rotate(this.angle)
    this.ctx.translate(-this.x - this.w / 2, -this.y - this.h / 2)

    super.draw({ sx: spriteData.sx, sy: spriteData.sy })
    this.ctx.restore()
  }
}
